package jmind.core.spring;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.URLDecoder;
import java.nio.charset.Charset;

import jmind.core.log.LogUtil;
import jmind.base.util.GlobalConstants;

import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.util.FileCopyUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;

/**
 <bean
 class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
 <property name="ignoreDefaultModelOnRedirect" value="true"></property>
 <property name="messageConverters">
 <list>

 <bean id="jsonConverter" class="jmind.core.spring.MappingFastjsonHttpMessageConverter">
 <property name="supportedMediaTypes">
 <list>
 <value>text/plain;charset=utf-8</value>
 <value>application/json;charset=UTF-8</value>
 </list>
 </property>
 <property name="features">
 <array value-type="com.alibaba.fastjson.serializer.SerializerFeature">
 <value>WriteDateUseDateFormat</value>
 <value>DisableCircularReferenceDetect</value>
 </array>
 </property>
 </bean>

 </list>
 </property>
 </bean>

 <bean id="WriteDateUseDateFormat"
 class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
 <property name="staticField"
 value="com.alibaba.fastjson.serializer.SerializerFeature.WriteDateUseDateFormat"></property>
 </bean>
 <bean id="DisableCircularReferenceDetect"
 class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
 <property name="staticField"
 value="com.alibaba.fastjson.serializer.SerializerFeature.DisableCircularReferenceDetect"></property>
 </bean>
 * @see MappingJacksonHttpMessageConverter
 * @see FastJsonHttpMessageConverter
 * @see StringHttpMessageConverter
 * Compatible Spring MVC version 4.2-
 * @author wbxie
 * 2014-1-3
 */
public class MappingFastjsonHttpMessageConverter extends AbstractHttpMessageConverter<Object> {

    public static final MediaType DEFAULT_TYPE = new MediaType("text", "plain", Charset.forName(GlobalConstants.UTF8));

    public MappingFastjsonHttpMessageConverter() {

        super(DEFAULT_TYPE, MediaType.ALL);

    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return true;
    }

    @Override
    public boolean canRead(Class<?> clazz, MediaType mediaType) {
        return true;
    }

    @Override
    public boolean canWrite(Class<?> clazz, MediaType mediaType) {
        return true;
    }

    /**
     * 只支持post的 对象传输， 当时get是，流里面读出的数据为空
     * @RequestBody  走这里 ,
     * 参数用@ModelAttribute  既支持post  也支持get
     * 参数直接是pojo的属性
     * 
     */
    @Override
    protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) throws IOException,
            HttpMessageNotReadableException {
        String param = FileCopyUtils
                .copyToString(new InputStreamReader(inputMessage.getBody(), GlobalConstants.UTF8));
        param = URLDecoder.decode(param, GlobalConstants.UTF8);
        LogUtil.debug("MappingFastjsonHttpMessageConverter  clazz={},body= {}", clazz, param);
        if (clazz.equals(String.class)) {
            return param;
        }

        if (param.startsWith("{") && param.endsWith("}")) { // json格式直接转换,这里判断一下，是怕json格式里面的数据也包含= 。所以先加一个判断
            return JSON.parseObject(param, clazz);
        }

        if (param.contains("=")) { // 参数形式，手动转换 ，支持post参数提交. 参考httpClient.postBody 方法  但HttpDefault会在末尾增加一个=，不知道为什么。
            JSONObject jo = new JSONObject();
            String[] split = param.split(GlobalConstants.DELIM);
            for (String s : split) {
                String[] ss = s.split("=");
                if (ss.length == 2) {
                    jo.put(ss[0], ss[1]);
                }
            }
            if (!jo.isEmpty())
                return JSON.toJavaObject(jo, clazz);
        }
        return JSON.parseObject(param, clazz);
    }

    @Override
    protected void writeInternal(Object t, HttpOutputMessage outputMessage) throws IOException,
            HttpMessageNotWritableException {
        // 非常重要，设置页面展示编码
        outputMessage.getHeaders().setContentType(DEFAULT_TYPE);
        if (t == null)
            return;
        if (t instanceof String) {
            FileCopyUtils.copy((String) t, new OutputStreamWriter(outputMessage.getBody(), GlobalConstants.UTF8));
        } else {
            String s = JSON.toJSONString(t, SerializerFeature.DisableCircularReferenceDetect,
                    SerializerFeature.WriteDateUseDateFormat);
            FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), GlobalConstants.UTF8));
        }

    }
}
